/*
 * Copyright 1999-2011 Alibaba Group.
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.dubbo.rpc.cluster;

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.RpcException;

import java.util.List;

/**
 * <pre>
 * Router. (SPI, Prototype, ThreadSafe)
 * 服务路由 包含一条路由规则，<b>路由规则决定了服务消费者的调用目标，即规定了服务消费者可调用哪些服务提供者。
 * 路由规则在发起一次RPC调用前起到过滤目标服务器地址的作用，过滤后的地址列表，将作为消费端最终发起RPC调用的备选地址。</b>
 *
 * Dubbo 目前提供了三种服务路由实现，分别为:
 *  1、条件路由 ConditionRouter  - 最常使用
 *  2、脚本路由 ScriptRouter
 *  3、标签路由 TagRouter        - 标签路由是一个新的实现，暂时还未发布，该实现预计会在 2.7.x 版本中发布
 *
 * <a href="http://en.wikipedia.org/wiki/Routing">wiki - Routing</a>
 *
 * <b>通过dubbo的路由规则，可做到：</b>
 * 排除预发布机：=> host != 172.22.3.91
 * 白名单 ：host != 10.20.153.10,10.20.153.11 =>
 * 黑名单：host = 10.20.153.10,10.20.153.11 =>
 * 服务寄宿在应用上，只暴露一部分的机器，防止整个集群挂掉：=> host = 172.22.3.1*,172.22.3.2*
 * 为重要应用提供额外的机器：application != kylin => host != 172.22.3.95,172.22.3.96
 * 读写分离：
 *      method = find*,list*,get*,is* => host = 172.22.3.94,172.22.3.95,172.22.3.96
 *      method != find*,list*,get*,is* => host = 172.22.3.97,172.22.3.98
 *  前后台分离：
 *      application = bops => host = 172.22.3.91,172.22.3.92,172.22.3.93
 *      application != bops => host = 172.22.3.94,172.22.3.95,172.22.3.96
 *  隔离不同机房网段： host != 172.22.3.* => host != 172.22.3.*
 *  提供者与消费者部署在同集群内，本机只访问本机的服务： => host = $host
 *  详细见<a href="http://dubbo.apache.org/zh-cn/docs/user/demos/routing-rule-deprecated.html">用户文档 -》 示例 -》 路由规则</a>
 *
 * </pre>
 * @author chao.liuc
 * @see com.alibaba.dubbo.rpc.cluster.Cluster#join(Directory)
 * @see com.alibaba.dubbo.rpc.cluster.Directory#list(Invocation)
 */
public interface Router extends Comparable<Router> {

    /**
     * get the router url.
     *
     * @return url
     */
    URL getUrl();

    /**
     * <pre>
     *
     * 服务目录在刷新 Invoker 列表的过程，及{@link Directory#list(Invocation) }方法
     * 会通过 Router 进行服务路由，<b>筛选出符合路由规则的服务提供者</b>
     *
     * </pre>
     * @param invokers
     * @param url        refer url
     * @param invocation
     * @return routed invokers
     * @throws RpcException
     */
    <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;

}